<?php // $Id: reserve.php 12 2008-07-30 17:28:32Z the.sk89q $

/**
 * reserve.php - does the work of reserving
 *
 * @version: $Id: reserve.php 12 2008-07-30 17:28:32Z the.sk89q $
 * @license http://www.gnu.org/copyleft/gpl.html
 * @package dpmatchreserve
 * 
 */

require_once "./common.php";
require_once "include/DigitalPaintServer.php";

$smarty->assign('title', 'Lease a Match Server');

$errors = array();

// ===============================
// Get input
// ===============================

$server = $_POST['server'];
$password = $_POST['password'];
$login_password = $_POST['login'];
$bot_check = trim($_POST['botcheck']);

$server_info = @$CONFIG['servers'][$server];

if (!isset($CONFIG['servers'][$server]) && ($CONFIG['enable_autoselect'] && $server != "autoselect")) {
    $errors[] = 'A valid server was not selected. Select a valid server to lease.';
}

if (strval($password) === "") {
    $errors[] = 'A password must be provided for players to use to login.';
} else if (preg_match("#[^A-Za-z0-9\\-_!@\\#\\$%\\^&\\*\\(\\)\\+=\\\\/\\{\\}\\[\\]\\.,\\?><~`\\|:]#", $password)) {
    $errors[] = 'The password provided contained invalid characters. Stick to standard ASCII characters. No spaces are allowed.';
} else if (strlen($password) > 30) {
    $errors[] = 'The password is too long. Shorten it.';
}

if (strval($login_password) === "") {
    $errors[] = 'A login password must be provided for you to use to change the map and manage players.';
} else if (preg_match("#[^A-Za-z0-9\\-_!@\\#\\$%\\^&\\*\\(\\)\\+=\\\\/\\{\\}\\[\\]\\.,\\?><~`\\|:]#", $login_password)) {
    $errors[] = 'The login password provided contained invalid characters. Stick to standard ASCII characters. No spaces are allowed.';
} else if (strlen($login_password) > 30) {
    $errors[] = 'The login password is too long. Shorten it.';
}

if ($CONFIG['bot_check_string'] && $bot_check != $CONFIG['bot_check_string']) {
    $errors[] = 'Enter the correct value for the spam-bot check';
}

// ===============================
// Process custom settings
// ===============================

$custom_vars = array();

foreach ($CONFIG['user_settings'] as $cvar => $opt) {
    $input = $_POST["var_$cvar"];
    if (strval($input) === "") continue;
    
    if ($opt['type'] == 'int') {
        if (!is_numeric($input)) {
            $errors[] = "The value of <em>$cvar</em> must be an integer";
        } else if ($input < $opt['min']) {
            $errors[] = "The value of <em>$cvar</em> must be equal to or greater than {$opt['min']}";
        } else if ($input > $opt['max']) {
            $errors[] = "The value of <em>$cvar</em> must be equal to or less than {$opt['max']}";
        } else {
            $custom_vars[$cvar] = intval($input);
        }
    } else if ($opt['type'] == 'float') {
        if (!is_numeric($input)) {
            $errors[] = "The value of <em>$cvar</em> must be a float";
        } else if ($input < $opt['min']) {
            $errors[] = "The value of <em>$cvar</em> must be equal to or greater than {$opt['min']}";
        } else if ($input > $opt['max']) {
            $errors[] = "The value of <em>$cvar</em> must be equal to or less than {$opt['max']}";
        } else {
            $custom_vars[$cvar] = floatval($input);
        }
    } else if ($opt['type'] == 'bool') {
        if ($input == "true") {
            $custom_vars[$cvar] = '1';
        } else if ($input == "false") {
            $custom_vars[$cvar] = '0';
        }
    }
    /*else if ($opt['type'] == 'string') {
        if (strlen($input) > 200) {
            $errors[] = "The value of <em>$cvar</em> is too long";
        } else {
            $custom_vars[$cvar] = $input;
        }
    }*/
}

// ===============================
// Is the server available?
// Or auto-select as necessary
// ===============================

if (count($errors) == 0) {
    try {
        if ($CONFIG['enable_autoselect'] && $server == "autoselect") {
            $found_open = false;
            
            foreach ($CONFIG['servers'] as $server => $server_info) {
                $paintball = new DigitalPaintServer($server_info['host'], $server_info['port'], $server_info['rcon_password']);

                if (!$paintball->is_online()) {
                    continue;
                } else if (count($paintball->get_players()) > 0) {
                    continue;
                } else if ($CONFIG['grace_period'] > 0) {
                    $last_lease = @filemtime("cache/last_lease_$server");
                    
                    if ($last_lease > time()-$CONFIG['grace_period']) {
                        continue;
                    }
                }
                
                $found_open = true;
                break;
            }
            
            if (!$found_open) {
                $errors[] = "All servers are currently unavailable; please try again later";
            }
        } else {
            $paintball = new DigitalPaintServer($server_info['host'], $server_info['port'], $server_info['rcon_password']);

            if (!$paintball->is_online()) {
                $errors[] = "<em>".htmlspecialchars($server_info['name'])."</em> is currently offline; please try another server";
            } else if (count($paintball->get_players()) > 0) {
                $errors[] = "<em>".htmlspecialchars($server_info['name'])."</em> is currently in use; please try another server";
            } else if ($CONFIG['grace_period'] > 0) {
                $last_lease = @filemtime("cache/last_lease_$server");
                
                if ($last_lease > time()-$CONFIG['grace_period']) {
                    $errors[] = "<em>".htmlspecialchars($server_info['name'])."</em> was leased by another individual too recently (and it is in the grace period); try another server";
                }
            }
        }
    } catch (DPSBadRCONPasswordException $e) {
        show_fatal_error("Please report this error to the webmaster of this website: the configured RCON password for <em>".htmlspecialchars($server_info['name'])."</em> is incorrect");
    } catch (DPSRCONPasswordUnsetException $e) {
        show_fatal_error("Please report this error to the webmaster of this website: there is no configured RCON password for <em>".htmlspecialchars($server_info['name'])."</em>");
    } catch (DPSConnectionException $e) {
        show_fatal_error("The connection to <em>".htmlspecialchars($server_info['name'])."</em> was lost; please try again");
    }
}

// ===============================
// Any errors?
// ===============================

if (count($errors) > 0) {
    $smarty->assign('errors', $errors);
    $smarty->display('error.tpl');
    exit;
}

// ===============================
// Lease it out
// ===============================

// Grace period
if ($CONFIG['grace_period'] > 0) {
    if (!$fp = @fopen("cache/last_lease_$server", "w")) {
        show_fatal_error("Please report this error to the webmaster of this website: could not write lease grace tracking files to the cache directory (chmod may be necessary)");
    }
    fclose($fp);
}

try {
    // Load the default map
    if (isset($CONFIG['default_map']) && !empty($CONFIG['default_map'])) {
        if ($CONFIG['use_map_command']) {
            $paintball->rcon("map ".$CONFIG['default_map']);
        } else {
            $paintball->rcon_new_map($CONFIG['default_map']);
        }
    }
    
    // What variables do we need to change?
    $login_vars = array('password' => $password,
                        "oppass{$server_info['op_pass_num']}" => $login_password);

    $changed_vars = array_merge($CONFIG['default_settings'], $custom_vars, $login_vars);

    foreach ($changed_vars as $cvar => $value) {
        $paintball->rcon_set_variable($cvar, $value);
    }
    
    // Execute commands
    $commands = explode("\n", $CONFIG['exec_commands_post']);
    foreach ($commands as $command) {
        $command = trim($command);
        if (!$command) {
            continue;
        }   
        
        $paintball->rcon($command);
    }
} catch (DPSBadRCONPasswordException $e) {
    show_fatal_error("Please report this error to the webmaster of this website: the configured RCON password for <em>".htmlspecialchars($server_info['name'])."</em> is incorrect");
} catch (DPSRCONPasswordUnsetException $e) {
    show_fatal_error("Please report this error to the webmaster of this website: there is no configured RCON password for <em>".htmlspecialchars($server_info['name'])."</em>");
} catch (DPSConnectionException $e) {
    show_fatal_error("The connection to <em>".htmlspecialchars($server_info['name'])."</em> was lost; please try again");
}

// ===============================
// Send it off
// ===============================

header(sprintf("Location: {$CONFIG['base_url']}/play.php?server=%d&password=%s&login=%s", $server, urlencode($password), urlencode($login_password)));
exit;

